package com.zxshhy.service.impl;

import com.zxshhy.entity.Account;
import com.zxshhy.mapper.AccountMapper;
import com.zxshhy.mapper.AccountTCCMapper;
import com.zxshhy.service.BalanceTCCService;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Objects;


/**
 * @author zxs
 */
@Service
@Slf4j
public class BalanceTCCServiceImpl implements BalanceTCCService {
    
    private static final String ERROR_USER_ID = "1002";
    
    @Resource
    private AccountTCCMapper accountTCCMapper;

    /**
     * try一阶段：冻结扣减用户金额
     * @param userId
     * @param money
     */
    @Transactional
    @Override
    public boolean debit(String userId, int money){
        log.info("=============冻结用户账户余额=================");
        log.info("当前 XID: {}", RootContext.getXID());
        checkBalance(userId, money);
        log.info("开始冻结用户 {} 余额", userId);
        //冻结金额
        Integer record = accountTCCMapper.freezeBalance(userId,money);
        log.info("冻结用户 {} 余额结果:{}", userId, record > 0 ? "操作成功" : "扣减余额失败");
        if(record == 0) throw new RuntimeException("TCC-->账户余额冻结try异常");
        return record > 0;
    }

    /**
     * try一阶段成功，提交扣减冻结余额
     * @param actionContext
     * @return
     */
    @Override
    public boolean commit(BusinessActionContext actionContext) {
        log.info("=============提交成功，扣减冻结金额=================");
        String userId = actionContext.getActionContext("userId").toString();
        int money = (int) actionContext.getActionContext("money");
        //扣减冻结金额
        int count = accountTCCMapper.reduceFreezeBalance(userId, money);
        if(count == 0) throw new RuntimeException("TCC-->扣减冻结余额commit异常");
        return count > 0;
    }

    /**
     * 异常回滚，解冻账户余额
     * @param actionContext
     * @return
     */
    @Override
    public boolean rollback(BusinessActionContext actionContext) {
        log.info("=============异常回滚，解冻金额=================");
        String userId = actionContext.getActionContext("userId").toString();
        int money = (int) actionContext.getActionContext("money");
        //解冻金额
        int isSuccess = accountTCCMapper.unfreezeBalance(userId, money);
        return isSuccess > 0;
    }

    /**
     * 检查账户余额是否充足
     * @param userId
     * @param money
     */
    private void checkBalance(String userId, int money){
        log.info("检查用户 {} 余额", userId);
        Account account = accountTCCMapper.selectByUserId(userId);
        if (Objects.isNull(account) || account.getMoney() < money) {
            log.warn("用户[{}]的账户余额不足，当前账户余额:{}，需扣减余额:{}", userId, Objects.isNull(account)?0:account.getMoney(),money);
            throw new RuntimeException("余额不足");
        }
    }
}
